
// 计算body的高度
function bodyHeight() {
  document.body.style.height = window.innerHeight + 'px';
  window.addEventListener('resize', function () {
    var newViewportHeight = window.innerHeight;
    document.body.style.height = newViewportHeight + 'px';
  });
}

/**
 * 将一个对象的值拼接成url
 * @obj 要拼接成查询字符串，注意，对象里面的属性值不能是对象类型，如果是对象类型，则会转换成JSON字符串再拼接
 * @pathname 传入的url，可以不传。
 **/
function setUrlforObject(obj, pathname = '') {
  if (Object.keys(obj).length === 0) return pathname;
  let search = ''
  pathname ? (pathname.indexOf('?') !== -1 ? (pathname.length - 1 == pathname.indexOf("?") ? search = pathname : search = pathname + "&") : search = pathname + "?") : search = "?";
  Object.keys(obj).forEach(function (item) {
    if (obj.hasOwnProperty(item) && typeof obj[item] !== "object") {
      search += item + '=' + obj[item] + '&';
    }
    if (obj.hasOwnProperty(item) && typeof obj[item] === "object") {
      search += item + '=' + JSON.stringify(obj[item]) + '&';
    }
  })
  search = search.substr(0, search.length - 1)
  return search;
}

/**
 * 将url解析成json队形
 * @url 如果有不是从location对象中获取的url，可以使用url参数传入url的字符串。
 * 返回一个json对象：
 *  url_：基础的请求地址，没有参数。
 *  其他参数，以键值对形式。
 **/
function getSearchToJson(url) {
  var obj = {}
  var urlAll = url ? url : decodeURIComponent(location.search);
  var urlArr = urlAll.split("?")
  if (urlArr.length !== 2) return obj;
  var searchArr = urlArr[1].split("&");
  for (let index = 0; index < searchArr.length; index++) {
    var s_ = searchArr[index].split("=");
    obj[s_[0]] = s_[1]
  }
  return obj;
}

/** 
*获取url上的数据。修改url。
*/
function url(obj = {}) {
  if (Object.keys(obj).length == 0) return getSearchToJson();
  let o = getSearchToJson();
  o = Object.assign(o, obj);
  history.pushState({}, '', location.origin + location.pathname + setUrlforObject(o));
  return o;
}

// g根据宽带来判断是否是移动设备
function isMobileDevice() {
  // 设定一个阈值，通常移动设备宽度小于这个值  
  const mobileWidthThreshold = 768; // 这个值可以根据需要调整  
  // 获取视口宽度  
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
  // 判断视口宽度是否小于阈值  
  return viewportWidth <= mobileWidthThreshold;
}

// 给页面添加style标签，并带有id
// append：默认是追加到对应id标签中，设置为false则替换对应标签的内容
function setStyle(cssContent, option = { id: 'setStyleTest', append: true }) {
  var styleTag;
  if (document.getElementById(option.id)) {
    styleTag = document.getElementById(option.id);
  } else {
    // 1. 创建一个新的<style>标签  
    styleTag = document.createElement('style');
    // 2. 设置<style>标签的ID  
    styleTag.id = option.id;
    // 4. 将<style>标签添加到<head>部分  
    document.head.appendChild(styleTag);
  }
  // 3. 给<style>标签添加CSS样式  
  if (styleTag.styleSheet) { // 对于旧版本的IE  
    option.append
      ? styleTag.styleSheet.cssText = cssContent
      : styleTag.innerHTML = cssContent;
  } else { // 对于其他浏览器  
    option.append
      ? styleTag.appendChild(document.createTextNode(cssContent))
      : styleTag.innerHTML = cssContent;
  }
}

// 检查某个元素是否在可视区（viewport）
function isElementInViewport(el) {
  // 获取元素的边界信息  
  var rect = el.getBoundingClientRect();
  // 视口的高度和宽度（考虑滚动条）  
  var viewHeight = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
  var viewWidth = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
  // 检查元素是否在视口内  
  return !(rect.bottom < 0 || rect.right < 0 || rect.top > viewHeight || rect.left > viewWidth);
}
// 检查某个元素是否在可视区（viewport）
function isInViePortOfOne(el) {
  const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
  const offsetTop = el.offsetTop;
  const scollTop = document.documentElement.scrollTop
  const top = offsetTop - scollTop;
  return top <= viewPortHeight && top >= 0
}
// 检查某个元素是否在可视区（viewport）
function isElementInViewportOfObserver(element, callbackIn, callbackOut) {
  const options = {
    root: null, // 观察者根元素，默认为浏览器视口
    threshold: 0 // 触发回调的交叉比例，默认为 0 (完全进入视口时触发)
  };
  const observer = new IntersectionObserver((entries) => {
    // 回调函数中的 entries 包含被观察元素的信息
    if (entries[0].isIntersecting) {
      callbackIn && callbackIn(element)
    } else {
      callbackOut && callbackOut(element)
    }
  }, options);

  observer.observe(element);
}

// 获取所有iframe里面的document和body
function getAllDocumentFormIframe() {
  var iframes = document.getElementsByTagName('iframe');
  if (iframes.length == 0) return {};
  var iframeDocs = [], iframeBodys = [];
  for (var i = 0; i < iframes.length; i++) {
    // 假设iframe的id是'myIframe'  
    var iframe = iframes[i];
    // 确保iframe的文档已经加载完成  
    if (iframe.contentDocument || iframe.contentWindow.document) {
      let d = iframe.contentDocument || iframe.contentWindow.document;
      let b = d.body;
      iframeDocs.push(d)
      iframeBodys.push(b)
    } else {
      // iframe可能还没有加载完成，或者受到同源策略的限制  
      console.log('iframe is not available yet or cross-origin restrictions apply');
    }
  }
  return { iframeDocs, iframeBodys }
}

// 获取目标元素下的所有子元素。仅返回元素的直接子元素，而不包括更深层次的子孙元素
function getAllChildElements(parentElement) {
  return Array.from(parentElement.children);
}


/**
* 将指定日期时间或当前日期时间转换成指定的格式。
* format("MM/DD/YYYY hh:mm") 
* @fmt {String} 日期格式
* @timestamp {Date} 标准时间。选填。
*/
function formatDate(fmt, timestamp) {
  const date = timestamp ? new Date(timestamp) : new Date()
  const o = {
    "Y+": date.getFullYear(),
    "M+": date.getMonth() + 1,     // 月
    "D+": date.getDate(),          // 日
    "h+": date.getHours(),         // 时
    "m+": date.getMinutes(),       // 分
    "s+": date.getSeconds(),       // 秒
    "W": date.getDay()             // 周
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(RegExp.$1, () => {
        if (k === 'W') {                                    // 星期几
          const week = ['日', '一', '二', '三', '四', '五', '六']
          return week[o[k]]
        } else if (k === 'Y+' || RegExp.$1.length == 1) {    // 年份 or 小于10不加0
          return o[k]
        } else {
          return ("00" + o[k]).substr(("" + o[k]).length)  // 小于10补位0
        }
      })
    }
  }
  return fmt
}

// 使一个元素自动滚动到可视区
function scrollToElement(element) {
  if (element) {
    element.scrollIntoView({
      behavior: 'smooth', // 平滑滚动  
      block: 'center'     // 滚动到视口中间  
    });
  }
}

// 通过关键字判断设备类型
function detectDeviceType() {
  const userAgent = navigator.userAgent || navigator.vendor || window.opera;
  // 移动设备正则表达式  
  const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
  // 平板设备正则表达式（主要针对iPad，其他平板可能需要根据实际情况调整）  
  const tabletRegex = /iPad/i;
  if (mobileRegex.test(userAgent)) {
    if (tabletRegex.test(userAgent)) {
      return 'Tablet';
    } else {
      return 'Mobile';
    }
  } else {
    return 'Other';
  }
}

// 根据屏幕宽度来判断设备类型
function detectDeviceTypeByScreenWidth() {
  const screenWidth = window.innerWidth;
  if (screenWidth <= 768) {
    // 通常认为小于或等于768px是移动设备  
    return 'Mobile';
  } else if (screenWidth <= 1024) {
    // 有些平板设备的屏幕宽度可能在这个范围内  
    return 'Tablet';
  } else {
    // 大于1024px通常认为是桌面设备或其他大屏幕设备  
    return 'Other';
  }
}

//  操作indexDB。用于保存图片和图书数据 。start
let booksData_imgsData = idbKeyval.createStore('booksData-imgsData', 'booksData_imgsData');
function set_booksData_imgsData(title, data) { return set(title, data, booksData_imgsData); }
function get_booksData_imgsData(title) { return get(title, booksData_imgsData); }
function del_booksData_imgsData(title) { return del(title, booksData_imgsData); }
//  操作indexDB。用于保存图片和图书数据 。end
